﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlServerCe;
using System.Globalization;
using Loki.Data;
using Loki.Utils;

namespace Luna.Data.SqlCe
{
    internal class SqlCeDatabaseCommand : LokiObject, IDatabaseCommand
    {
        private const string PARAMETER_PREFIX = "@";

        private const string DECIMAL_FORMATTER = "{0}";

        public virtual void AddParameter(IDataParameter P_Parameter)
        {
            _Parameters.Add((SqlCeParameter)P_Parameter);
        }

        public void AddDateParameter(string P_ValueName, DateTime P_Value)
        {
            if (P_Value.Year > 1752)
            {
                AddParameter(DatabaseUtils.PutValue<DateTime>(P_ValueName, P_Value, (x) => new SqlCeParameter(PARAMETER_PREFIX + P_ValueName, null)));
            }
            else
            {
                throw BuildError<NotSupportedException>("Not Supported");
            }
        }

        public void AddDecimalParameter(string P_ValueName, decimal P_Value)
        {
            AddParameter(DatabaseUtils.PutValue<string>(P_ValueName, string.Format(CultureInfo.CurrentUICulture, DECIMAL_FORMATTER, P_Value), (x) => new SqlCeParameter(PARAMETER_PREFIX + P_ValueName, SqlDbType.Decimal)));
        }

        public void AddParameter<T>(string P_ValueName, T P_Value)
        {
            if (P_Value is DateTime)
            {
                AddDateParameter(P_ValueName, Convert.ToDateTime(P_Value));
            }
            else if (typeof(T) == typeof(DateTime?) && P_Value != null)
            {
                AddDateParameter(P_ValueName, Convert.ToDateTime(P_Value));
            }
            /*else if (P_Value is decimal)
            {
                AddDecimalParameter(P_ValueName, Convert.ToDecimal(P_Value));
            }
            else if (typeof(T) == typeof(decimal?) && P_Value != null)
            {
                AddDecimalParameter(P_ValueName, Convert.ToDecimal(P_Value));
            }*/
            else
            {
                AddParameter(DatabaseUtils.PutValue<T>(P_ValueName, P_Value, (x) => new SqlCeParameter(PARAMETER_PREFIX + P_ValueName, default(T))));
            }
        }

        public void AddParameter<T>(string P_ValueName, T P_Value, Func<T> P_DefaultValue)
        {
            AddParameter(DatabaseUtils.PutValue<T>(P_ValueName, P_Value, (x) => new SqlCeParameter(PARAMETER_PREFIX + P_ValueName, default(T)), P_DefaultValue));
        }

        public SqlCeDatabaseCommand(string P_Name)
        {
            Name = P_Name;
            _Parameters = new List<SqlCeParameter>();
            Type = CommandType.Text;
        }

        public string Dump()
        {
            string L_TextCopy = this.Name;
            foreach (IDataParameter L_Param in Parameters)
            {
                L_TextCopy = L_TextCopy.Replace(L_Param.ParameterName, string.Format(DECIMAL_FORMATTER, L_Param.Value));
            }

            return L_TextCopy;
        }

        public string Name
        {
            get;
            private set;
        }

        public CommandType Type
        {
            get;
            private set;
        }

        private List<SqlCeParameter> _Parameters;

        public IEnumerable<IDataParameter> Parameters
        {
            get
            {
                return _Parameters;
            }
        }
    }
}
